package com.computergames.server.service.Deal;

import com.computergames.server.domain.ClientState;
import com.computergames.server.domain.Deck;
import com.computergames.server.domain.PokerCard;
import com.computergames.server.message.CreateRoomResponseMessage;
import com.computergames.server.message.cardMessage.BidResponseMessage;
import com.computergames.server.message.cardMessage.DealMessage;
import com.computergames.server.server.handler.CreateRoomRequestMessageHandler;
import com.computergames.server.server.session.RoomSessionFactory;
import com.computergames.server.server.session.SessionFactory;
import io.netty.channel.Channel;
import io.netty.util.AttributeKey;

import java.util.*;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.atomic.AtomicReference;
import java.util.stream.Collectors;
import java.util.stream.IntStream;


public class LandlordDealStrategy implements DealStrategy<PokerCard> {
    private static final LandlordDealStrategy INSTANCE = new LandlordDealStrategy();
    private enum DealPhase {HANDS, BOTTOM}

    private static final Map<String, AtomicReference<DealPhase>> roomDealPhase = new ConcurrentHashMap<>();
    private static final int CARDS_PER_PLAYER = 17;
    private static final int BOTTOM_CARDS = 3;

    private static final AttributeKey<String> LANDLORD_KEY = AttributeKey.valueOf("LANDLORD");
    private static final AttributeKey<String> POSITION_KEY = AttributeKey.valueOf("POSITION");
    private LandlordDealStrategy() {

    }

    public static LandlordDealStrategy getInstance() {
        return INSTANCE;
    }

    @Override
    public void dealCards(String roomName, Deck<PokerCard> deck, Map<String, Map<String, Integer>> playerBids) {
        AtomicReference<DealPhase> dealPhase = roomDealPhase.computeIfAbsent(roomName, k -> new AtomicReference<>(DealPhase.HANDS));
        List<Channel> channels = RoomSessionFactory.getRoomSession().getMembersChannel(roomName);
        Set<String> members = new LinkedHashSet<> (CreateRoomRequestMessageHandler.getRoomName_members().get(roomName));
        if (channels == null || deck == null) {
            throw new IllegalArgumentException("Channels and deck cannot be null.");
        }
        if (channels.isEmpty()) {
            throw new IllegalArgumentException("Channels list cannot be empty.");
        }
        if (deck.remainingCards() < (dealPhase.get() == DealPhase.HANDS ? CARDS_PER_PLAYER * channels.size() + BOTTOM_CARDS : BOTTOM_CARDS)) {
            throw new IllegalArgumentException("Not enough cards in the deck to deal.");
        }

        DealPhase currentPhase = dealPhase.get();
        if (currentPhase == DealPhase.HANDS) {
            List<PokerCard> cards = new ArrayList<>();
            List<String> positions = IntStream.range(0, channels.size())
                    .mapToObj(i -> String.valueOf((char) ('A' + i)))
                    .collect(Collectors.toList());
            int index = 0;
            for(String member : members){
                for(Channel channel : channels){
                    if(SessionFactory.getSession().getChannel(member) == channel){
                        String position = positions.get(index++);
                        channel.attr(POSITION_KEY).set(position);
                    }
                }
            }
            // 发手牌给每个玩家
            for (Channel channel : channels) {
                cards.clear();
                for (int i = 0; i < CARDS_PER_PLAYER; i++) {
                    cards.add(deck.drawCard());
                }
                // 将手牌列表转换为字符串并发送
//                String handStr = cards.stream()
//                        .map(Enum::name)
//                        .collect(Collectors.joining(", "));
//                channel.writeAndFlush(new BidResponseMessage(true, "手牌是：" + handStr));
                // 将手牌列表转换为数值列表，再转换为字符串并发送
                String handValues = cards.stream()
                        .map(PokerCard::getValue) // 提取每个PokerCard的value
                        .map(String::valueOf) // 将int转换为String
                        .collect(Collectors.joining(", ")); // 连接成一个字符串
                channel.writeAndFlush(new DealMessage(true, channel.attr(AttributeKey.valueOf("POSITION")).get() + handValues));
            }
            dealPhase.set(DealPhase.BOTTOM);// 切换到下一个阶段
        } else if (currentPhase == DealPhase.BOTTOM) {
            // 寻找叫牌值最高的玩家
            String landlordUsername = null;
            int maxBid = Integer.MIN_VALUE;
            for(Map.Entry<String, Map<String, Integer>> entry : playerBids.entrySet()){
                for(Map.Entry<String, Integer> bidEntry : entry.getValue().entrySet()){
                    if (bidEntry.getValue() > maxBid) {
                        maxBid = bidEntry.getValue();
                        landlordUsername = bidEntry.getKey(); // 记录最高叫牌的用户名
                    }
                }
            }
            // 获取landlordUsername对应的方位，即{A,B,C}
            String landlord = null;
            for(Map.Entry<String, Map<String, Integer>> entry : playerBids.entrySet()) {
                Map<String, Integer> innerMap = entry.getValue();
                // 获取内层Map的唯一键
                String key = innerMap.keySet().iterator().next();
                if(key.equals(landlordUsername)){
                    landlord = entry.getKey();
                }
            }
            Channel landlordChannel = SessionFactory.getSession().getChannel(landlordUsername);
            // 发送底牌给地主
            if (landlordChannel != null) {
                landlordChannel.attr(LANDLORD_KEY).set(landlord);
                List<PokerCard> bottomCards = new ArrayList<>();
                for (int i = 0; i < 3; i++) {
                    bottomCards.add(deck.drawCard());
                }
//                String bottomStr = bottomCards.stream()
//                        .map(Enum::name)
//                        .collect(Collectors.joining(", "));
                String bottomValues = bottomCards.stream()
                        .map(PokerCard::getValue) // 提取每个PokerCard的value
                        .map(String::valueOf) // 将int转换为String
                        .collect(Collectors.joining(", "));
                for (Channel channel : channels) {
                    if (!channel.attr(AttributeKey.valueOf("USER_IDENTIFIER")).get().equals(landlordUsername)){
                        channel.writeAndFlush(new BidResponseMessage(true, "地主是：" + landlordUsername + "底牌是：" + bottomValues));
                    }
                }
                landlordChannel.writeAndFlush(new BidResponseMessage(true, "你是地主，底牌是：" + bottomValues));
                bottomCards.clear();
            }
            // 发完底牌后，重置dealPhase，以便重新开始发牌过程
            dealPhase.set(DealPhase.HANDS);
        }
    }
}
